package com.gator.rabbitmq.pablo_rabbitmq.boot.rabbitmq.awesome.exchange_callback;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @Author PABLO
 * @Date 2022/6/6 18:47
 * @Desc 基于交换机失效的回调方法-->Producer
 */
@Component
@Slf4j
public class ExchangeCallBack implements RabbitTemplate.ConfirmCallback
        , RabbitTemplate.ReturnsCallback {

    //由于继承的接口是内部接口，需先获取该接口对应的类，而后set
    //可在bean初始化时调用init
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    /**
     * @Description: 交换机接受成功或失败均回调
     * @Author: PABLO
     * @Date: 2022/6/6 18:49
     * @Params: [correlationData 数据（id和数据信息如路由key，交换机等）,该消息产自于producer
     * , ack 确认标记, cause 失败原因]
     * @Return: void
     * <p>
     * 确认机制分类
     * public enum ConfirmType {
     * SIMPLE,
     * 此模式下，rabbitTemplate如调用waitForConfirms或waitForConfirmOrDie同步等待方法如返回false将关闭channel信道，是单个确认
     * 反之和CORRELATED效果相同
     * CORRELATED, 发送到交换机后回调
     * NONE 默认禁用
     * }
     **/
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData != null ? correlationData.getId() : "";
        if (ack) {
            log.info("交换机接受消息成功" +
                    "消息id" + id);
        } else {
            log.info("交换机接受消息失败" +
                    "消息id" + id + "失败原因：" +
                    cause);
        }
    }

    /**
     * @Description: 无效路由key的回调
     * @Author: PABLO
     * @Date: 2022/6/6 19:29
     * @Params: [returned]
     * @Return: void
     **/
    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.error("交换机收到无效key{},错误码:{},交换机:{},消息是{}"
                , returned.getRoutingKey()
                , returned.getReplyCode()
                , returned.getExchange()
                , new String(returned.getMessage().getBody()));

    }
}
